package discov

import (
	"fmt"
	"io/ioutil"
	"log"
	"net/http"
	"net/url"
	"strings"

	"github.com/beego/beego/v2/client/httplib"

	"github.com/pkg/errors"
)

type Client struct {
	Conf     Conf
	Discover Discover
}

func NewClient(conf Conf) *Client {
	discover := MustNewDiscover(conf)
	return &Client{
		Conf:     conf,
		Discover: discover,
	}
}

func (c *Client) CallWithHeader(path string, method string, params map[string]string, jsonParams interface{}, headers map[string]string) ([]byte, error) {
	endPoints, err := c.Discover.Endpoint()
	if err != nil {
		log.Println(path, errors.Wrap(err, "discover error"))
		return nil, err
	}
	requestUrl := fmt.Sprintf("%s%s", endPoints, path)
	method = strings.ToUpper(method)

	request := httplib.NewBeegoRequest(requestUrl, method)
	if c.Conf.Debug && len(c.Conf.Proxy) > 0 {
		proxyUrl, _ := url.Parse(c.Conf.Proxy)
		proxy := http.ProxyURL(proxyUrl)
		request.SetProxy(proxy)
	}

	if params != nil {
		for k, v := range params {
			request.Param(k, v)
		}
	} else if jsonParams != nil {
		request.JSONBody(jsonParams)
	}
	for k, v := range headers {
		request.Header(k, v)
	}

	response, err := request.DoRequest()

	if err != nil {
		log.Printf("%s %+v\n", path, errors.Wrap(err, "request err"))
		return nil, errors.Wrap(err, "request err")
	}
	if response.StatusCode != http.StatusOK {
		log.Printf("%s %+v\n", path, errors.Wrap(RequestErr, "request status error"))
		return nil, RequestErr
	}
	body := response.Body
	defer body.Close()
	content, err := ioutil.ReadAll(body)
	if err != nil {
		log.Printf("%s %+v\n", path, errors.Wrap(err, "read content error"))
		return nil, errors.Wrap(err, "read content error")
	}
	log.Println(path, string(content))

	return content, nil
}
